package com.ncmmall.application.business.marketing;

import com.feijin.commons.lang.Requires;
import com.ncmmall.domain.business.goods.Goods;
import com.ncmmall.domain.business.goods.QGoods;
import com.ncmmall.domain.business.goods.channel.GoodsChannel;
import com.ncmmall.domain.business.goods.channel.QGoodsChannel;
import com.ncmmall.domain.business.marketing.shoppingcard.QShoppingCardRecord;
import com.ncmmall.domain.business.marketing.shoppingcard.ShoppingCard;
import com.ncmmall.domain.business.marketing.shoppingcard.ShoppingCardAddress;
import com.ncmmall.domain.business.marketing.shoppingcard.ShoppingCardAddressRepository;
import com.ncmmall.domain.business.marketing.shoppingcard.ShoppingCardChannel;
import com.ncmmall.domain.business.marketing.shoppingcard.ShoppingCardChannelRepository;
import com.ncmmall.domain.business.marketing.shoppingcard.ShoppingCardGoods;
import com.ncmmall.domain.business.marketing.shoppingcard.ShoppingCardGoodsRepository;
import com.ncmmall.domain.business.marketing.shoppingcard.ShoppingCardMerchant;
import com.ncmmall.domain.business.marketing.shoppingcard.ShoppingCardMerchantRepository;
import com.ncmmall.domain.business.marketing.shoppingcard.ShoppingCardRecord;
import com.ncmmall.domain.business.marketing.shoppingcard.ShoppingCardRecordRepository;
import com.ncmmall.domain.business.marketing.shoppingcard.ShoppingCardRepository;
import com.ncmmall.domain.security.user.QWebUser;
import com.ncmmall.domain.security.user.WebUser;
import com.ncmmall.querychannel.service.QueryChannelService;
import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.sql.Timestamp;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 购物卡
 */
@Service
@Transactional
public class ShoppingCardApplication {

    @Autowired
    private ShoppingCardRepository shoppingCardRepository;

    @Autowired
    private ShoppingCardAddressRepository shoppingCardAddressRepository;

    @Autowired
    private ShoppingCardChannelRepository shoppingCardChannelRepository;

    @Autowired
    private ShoppingCardMerchantRepository shoppingCardMerchantRepository;

    @Autowired
    private ShoppingCardGoodsRepository shoppingCardGoodsRepository;

    @Autowired
    private ShoppingCardRecordRepository shoppingCardRecordRepository;

    @Autowired
    private QueryChannelService queryChannelService;

    /**
     * 添加购物卡
     *
     * @param card 购物卡
     */
    public void create(ShoppingCard card) {
        int count = queryChannelService.selectCount("select count(*) from mall_shopping_card where cardNo = :no", ImmutableMap.of("no", card.getCardNo()));
        Requires.isTrue(count == 0, "发放编号重复");
        Requires.isTrue(card.getFaceValue() > 0, "面值必须大于0");
        Requires.isTrue(card.getPrice() < card.getFaceValue(), "售价必须小于面值");
        Requires.isTrue(card.getNumber() > 0, "购物卡数量必须大于0");

        Timestamp now = new Timestamp(System.currentTimeMillis());

        Requires.notEmpty(card.getChannels(), "请选择品类");
        List<ShoppingCardChannel> channels = card.getChannels().stream()
                .filter(shoppingCardChannel -> shoppingCardChannel.getGoodsChannel() != null)
                .peek(shoppingCardChannel -> {
                    long channelId = shoppingCardChannel.getGoodsChannel().getId();
                    shoppingCardChannel.setCreateTime(now);
                    shoppingCardChannel.setShoppingCard(card);
                    shoppingCardChannel.setGoodsChannel(queryChannelService.findOne(QGoodsChannel.goodsChannel.id.eq(channelId), GoodsChannel.class));
                }).collect(Collectors.toList());

        //指定地区
        List<ShoppingCardAddress> addresses = Lists.newArrayList();
        if (card.getAreaType() == 2) {
            Requires.notEmpty(card.getAddresses(), "请选择指定地区");
            addresses = card.getAddresses().stream().peek(shoppingCardAddress -> {
                shoppingCardAddress.setShoppingCard(card);
                shoppingCardAddress.setCreateTime(now);
            }).collect(Collectors.toList());
        }

        if (card.getValidType() == 1) {
            //固定日期
            String dateStr = card.getDateStr();
            Requires.hasLength(dateStr, "请选择日期");
            List<String> dates = Splitter.on(" - ").splitToList(dateStr);
            card.setValidStartTime(Timestamp.valueOf(dates.get(0) + " 00:00:00"));
            card.setValidEndTime(Timestamp.valueOf(dates.get(1) + " 23:59:59"));
        } else {
            //几天后使用
            Requires.isTrue(card.getValidDays() > 0, "有效期必须大于0天");
        }

        //指定商家
        List<ShoppingCardMerchant> merchants = Lists.newArrayList();
        if (card.getMerchantType() == 2) {
            Requires.notEmpty(card.getMerchants(), "请选择指定商家");
            merchants = card.getMerchants().stream().filter(merchant -> merchant.getMerchant().getId() != 0).peek(shoppingCardMerchant -> {
                long merchantId = shoppingCardMerchant.getMerchant().getId();
                shoppingCardMerchant.setShoppingCard(card);
                shoppingCardMerchant.setCreateTime(now);
                shoppingCardMerchant.setMerchant(queryChannelService.findOne(QWebUser.webUser.id.eq(merchantId), WebUser.class));
            }).collect(Collectors.toList());
        }

        //指定商品
        List<ShoppingCardGoods> goods = Lists.newArrayList();
        if (card.getGoodsType() == 2) {
            Requires.notEmpty(card.getGoods(), "请选择指定商品");
            goods = card.getGoods().stream().filter(item -> item.getGoods().getId() != 0).peek(shoppingCardGoods -> {
                long goodsId = shoppingCardGoods.getGoods().getId();
                shoppingCardGoods.setShoppingCard(card);
                shoppingCardGoods.setCreateTime(now);
                shoppingCardGoods.setGoods(queryChannelService.findOne(QGoods.goods.id.eq(goodsId), Goods.class));
            }).collect(Collectors.toList());
        }

        card.setCreateTime(new Timestamp(System.currentTimeMillis()));
        card.setStatus(1);
        shoppingCardRepository.save(card);

        shoppingCardChannelRepository.save(channels);
        if (CollectionUtils.isNotEmpty(addresses)) {
            shoppingCardAddressRepository.save(addresses);
        }
        if (CollectionUtils.isNotEmpty(merchants)) {
            shoppingCardMerchantRepository.save(merchants);
        }
        if (CollectionUtils.isNotEmpty(goods)) {
            shoppingCardGoodsRepository.save(goods);
        }
    }

    /**
     * 购物卡上架
     *
     * @param card 购物卡
     */
    public void enable(ShoppingCard card) {
        enableCheck(card);
        card.setStatus(2);
        card.setEnableTime(new Timestamp(System.currentTimeMillis()));
        shoppingCardRepository.save(card);
    }

    private void enableCheck(ShoppingCard card) {
        if (card.getValidType() == 1) {
            Requires.isTrue(card.getValidEndTime().getTime() > System.currentTimeMillis(), "购物卡" + card.getName() + "已过期");
        }
        Requires.isTrue(card.getSaleNumberCount() < card.getNumber(), "购物卡" + card.getName() + "已全部售完");
    }

    /**
     * 购物卡下架
     *
     * @param card 购物卡
     */
    public void disable(ShoppingCard card) {
        card.setStatus(1);
        shoppingCardRepository.save(card);
    }

    /**
     * 批量上架
     *
     * @param cards 购物卡列表
     */
    public void enables(List<ShoppingCard> cards) {
        Timestamp now = new Timestamp(System.currentTimeMillis());
        for (ShoppingCard card : cards) {
            enableCheck(card);
            card.setStatus(2);
            card.setEnableTime(now);
        }
        shoppingCardRepository.save(cards);
    }

    /**
     * 批量下架
     *
     * @param cards 购物卡列表
     */
    public void disables(List<ShoppingCard> cards) {
        for (ShoppingCard card : cards) {
            card.setStatus(1);
            List<ShoppingCardRecord> records = queryChannelService.findAll(QShoppingCardRecord.shoppingCardRecord.shoppingCard.id.eq(card.getId()).and(QShoppingCardRecord.shoppingCardRecord.status.eq(1)), ShoppingCardRecord.class);
            for (ShoppingCardRecord record : records) {
                record.setStatus(4);
            }
            shoppingCardRecordRepository.save(records);
        }
        shoppingCardRepository.save(cards);
    }

    /**
     * 自动下架
     * 有效期过了自动下架
     */
    public void autoDisable() {

        List<ShoppingCard> cards = queryChannelService.findAll("select c from ShoppingCard c where c.status = 2 and c.validType = 1 and c.validEndTime < :time", ImmutableMap.of("time", new Timestamp(System.currentTimeMillis())), ShoppingCard.class);
        if (CollectionUtils.isNotEmpty(cards)) {
            for (ShoppingCard card : cards) {
                card.setStatus(1);
            }
            shoppingCardRepository.save(cards);
        }

        List<ShoppingCardRecord> records = queryChannelService.findAll("select c from ShoppingCardRecord c where c.status != 4 and c.validEndTime < :time", ImmutableMap.of("time", new Timestamp(System.currentTimeMillis())), ShoppingCardRecord.class);
        if (CollectionUtils.isNotEmpty(records)) {
            for (ShoppingCardRecord record : records) {
                record.setStatus(4);
            }
            shoppingCardRecordRepository.save(records);
        }

    }


    /**
     * 系统赠送购物卡给用户
     *
     * @param shoppingCard 购物卡
     * @param user         赠送给哪个用户
     * @param system       当前操作的系统用户
     */
    public void present(ShoppingCard shoppingCard, WebUser user, WebUser system) {

        ShoppingCardRecord record = new ShoppingCardRecord();
        record.setUser(user);
        record.setShoppingCard(shoppingCard);
        record.setSource(2);
        record.setBalance(shoppingCard.getFaceValue());
        record.setRecipient(system);

        Timestamp now = new Timestamp(System.currentTimeMillis());
        record.setRecipientTime(now);
        record.setCreateTime(now);
        record.setStatus(1);

        if (shoppingCard.getValidType() == 1) {
            record.setValidStartTime(shoppingCard.getValidStartTime());
            record.setValidEndTime(shoppingCard.getValidEndTime());
        } else {
            record.setValidStartTime(now);
            Timestamp endTime = new Timestamp(now.getTime() + (long) shoppingCard.getValidDays() * 24 * 3600 * 1000);
            record.setValidEndTime(endTime);
        }
        shoppingCardRecordRepository.save(record);

        shoppingCard.setNumber(shoppingCard.getNumber() - 1);
        shoppingCardRepository.save(shoppingCard);
    }
}
